core/iter/traits/
accum.rs

1use crate::iter;
2use crate::num::Wrapping;
3
4/// Trait to represent types that can be created by summing up an iterator.
5///
6/// This trait is used to implement [`Iterator::sum()`]. Types which implement
7/// this trait can be generated by using the [`sum()`] method on an iterator.
8/// Like [`FromIterator`], this trait should rarely be called directly.
9///
10/// [`sum()`]: Iterator::sum
11/// [`FromIterator`]: iter::FromIterator
12#[stable(feature = "iter_arith_traits", since = "1.12.0")]
13#[rustc_on_unimplemented(
14    message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
15    label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
16)]
17pub trait Sum<A = Self>: Sized {
18    /// Takes an iterator and generates `Self` from the elements by "summing up"
19    /// the items.
20    #[stable(feature = "iter_arith_traits", since = "1.12.0")]
21    fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
22}
23
24/// Trait to represent types that can be created by multiplying elements of an
25/// iterator.
26///
27/// This trait is used to implement [`Iterator::product()`]. Types which implement
28/// this trait can be generated by using the [`product()`] method on an iterator.
29/// Like [`FromIterator`], this trait should rarely be called directly.
30///
31/// [`product()`]: Iterator::product
32/// [`FromIterator`]: iter::FromIterator
33#[stable(feature = "iter_arith_traits", since = "1.12.0")]
34#[rustc_on_unimplemented(
35    message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
36    label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
37)]
38pub trait Product<A = Self>: Sized {
39    /// Takes an iterator and generates `Self` from the elements by multiplying
40    /// the items.
41    #[stable(feature = "iter_arith_traits", since = "1.12.0")]
42    fn product<I: Iterator<Item = A>>(iter: I) -> Self;
43}
44
45macro_rules! integer_sum_product {
46    (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
47        #[$attr]
48        impl Sum for $a {
49            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
50                iter.fold(
51                    $zero,
52                    #[rustc_inherit_overflow_checks]
53                    |a, b| a + b,
54                )
55            }
56        }
57
58        #[$attr]
59        impl Product for $a {
60            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
61                iter.fold(
62                    $one,
63                    #[rustc_inherit_overflow_checks]
64                    |a, b| a * b,
65                )
66            }
67        }
68
69        #[$attr]
70        impl<'a> Sum<&'a $a> for $a {
71            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
72                iter.fold(
73                    $zero,
74                    #[rustc_inherit_overflow_checks]
75                    |a, b| a + b,
76                )
77            }
78        }
79
80        #[$attr]
81        impl<'a> Product<&'a $a> for $a {
82            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
83                iter.fold(
84                    $one,
85                    #[rustc_inherit_overflow_checks]
86                    |a, b| a * b,
87                )
88            }
89        }
90    )*);
91    ($($a:ty)*) => (
92        integer_sum_product!(@impls 0, 1,
93                #[stable(feature = "iter_arith_traits", since = "1.12.0")],
94                $($a)*);
95        integer_sum_product!(@impls Wrapping(0), Wrapping(1),
96                #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
97                $(Wrapping<$a>)*);
98    );
99}
100
101macro_rules! float_sum_product {
102    ($($a:ident)*) => ($(
103        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
104        impl Sum for $a {
105            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
106                iter.fold(
107                    -0.0,
108                    #[rustc_inherit_overflow_checks]
109                    |a, b| a + b,
110                )
111            }
112        }
113
114        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
115        impl Product for $a {
116            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
117                iter.fold(
118                    1.0,
119                    #[rustc_inherit_overflow_checks]
120                    |a, b| a * b,
121                )
122            }
123        }
124
125        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
126        impl<'a> Sum<&'a $a> for $a {
127            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
128                iter.fold(
129                    -0.0,
130                    #[rustc_inherit_overflow_checks]
131                    |a, b| a + b,
132                )
133            }
134        }
135
136        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
137        impl<'a> Product<&'a $a> for $a {
138            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
139                iter.fold(
140                    1.0,
141                    #[rustc_inherit_overflow_checks]
142                    |a, b| a * b,
143                )
144            }
145        }
146    )*)
147}
148
149integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
150float_sum_product! { f32 f64 }
151
152#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
153impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
154where
155    T: Sum<U>,
156{
157    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
158    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
159    /// occur, the sum of all elements is returned.
160    ///
161    /// # Examples
162    ///
163    /// This sums up every integer in a vector, rejecting the sum if a negative
164    /// element is encountered:
165    ///
166    /// ```
167    /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) };
168    /// let v = vec![1, 2];
169    /// let res: Result<i32, _> = v.iter().map(f).sum();
170    /// assert_eq!(res, Ok(3));
171    /// let v = vec![1, -2];
172    /// let res: Result<i32, _> = v.iter().map(f).sum();
173    /// assert_eq!(res, Err("Negative element found"));
174    /// ```
175    fn sum<I>(iter: I) -> Result<T, E>
176    where
177        I: Iterator<Item = Result<U, E>>,
178    {
179        iter::try_process(iter, |i| i.sum())
180    }
181}
182
183#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
184impl<T, U, E> Product<Result<U, E>> for Result<T, E>
185where
186    T: Product<U>,
187{
188    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
189    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
190    /// occur, the product of all elements is returned.
191    ///
192    /// # Examples
193    ///
194    /// This multiplies each number in a vector of strings,
195    /// if a string could not be parsed the operation returns `Err`:
196    ///
197    /// ```
198    /// let nums = vec!["5", "10", "1", "2"];
199    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
200    /// assert_eq!(total, Ok(100));
201    /// let nums = vec!["5", "10", "one", "2"];
202    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
203    /// assert!(total.is_err());
204    /// ```
205    fn product<I>(iter: I) -> Result<T, E>
206    where
207        I: Iterator<Item = Result<U, E>>,
208    {
209        iter::try_process(iter, |i| i.product())
210    }
211}
212
213#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
214impl<T, U> Sum<Option<U>> for Option<T>
215where
216    T: Sum<U>,
217{
218    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
219    /// elements are taken, and the [`None`] is returned. Should no [`None`]
220    /// occur, the sum of all elements is returned.
221    ///
222    /// # Examples
223    ///
224    /// This sums up the position of the character 'a' in a vector of strings,
225    /// if a word did not have the character 'a' the operation returns `None`:
226    ///
227    /// ```
228    /// let words = vec!["have", "a", "great", "day"];
229    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
230    /// assert_eq!(total, Some(5));
231    /// let words = vec!["have", "a", "good", "day"];
232    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
233    /// assert_eq!(total, None);
234    /// ```
235    fn sum<I>(iter: I) -> Option<T>
236    where
237        I: Iterator<Item = Option<U>>,
238    {
239        iter::try_process(iter, |i| i.sum())
240    }
241}
242
243#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
244impl<T, U> Product<Option<U>> for Option<T>
245where
246    T: Product<U>,
247{
248    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
249    /// elements are taken, and the [`None`] is returned. Should no [`None`]
250    /// occur, the product of all elements is returned.
251    ///
252    /// # Examples
253    ///
254    /// This multiplies each number in a vector of strings,
255    /// if a string could not be parsed the operation returns `None`:
256    ///
257    /// ```
258    /// let nums = vec!["5", "10", "1", "2"];
259    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
260    /// assert_eq!(total, Some(100));
261    /// let nums = vec!["5", "10", "one", "2"];
262    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
263    /// assert_eq!(total, None);
264    /// ```
265    fn product<I>(iter: I) -> Option<T>
266    where
267        I: Iterator<Item = Option<U>>,
268    {
269        iter::try_process(iter, |i| i.product())
270    }
271}